/**
 * @file sysfont12.c
 * @brief
 *
 * @version Fixed
 * @author yemit
 * @date 2012-06-17
 */
#include <sys/ioctl.h>
#include <stdint.h>
#include "flash.h"
#include "resource.h"
#include <key.h>
#include "device.h"
#include "config.h"
extern part_t * res_part;
extern res_entry_t sys_hzk;
extern res_entry_t sys_asc;
#ifdef CONFIG_PRINTER_FONT
extern res_entry_t prn_hzk;
extern res_entry_t prn_asc;
#endif

extern int lcd_fd;
extern lcd_info_t info;
extern void _lcd_disp_img(uint32_t x, uint32_t y,
                uint32_t w, uint32_t h, uint8_t * img);

static inline int read_sys_hzk(uint32_t offset, uint8_t * buf, uint32_t len)
{
        return part_read(res_part, offset + sys_hzk.offset, buf, len);
}

static inline int read_sys_asc(uint32_t offset, uint8_t * buf, uint32_t len)
{
        return part_read(res_part, offset + sys_asc.offset, buf, len);
}

#ifdef CONFIG_PRINTER_FONT
 int read_prn_hzk(uint32_t offset, uint8_t * buf, uint32_t len)
{
        return part_read(res_part, offset + prn_hzk.offset, buf, len);
}

int read_prn_asc(uint32_t offset, uint8_t * buf, uint32_t len)
{
        return part_read(res_part, offset + prn_asc.offset, buf, len);
}
#endif

int lcd_disp_string(uint32_t x, uint32_t y, char * string)
{
        char *s = string;
        uint8_t font_buf[24];
        lcd_block_t blk;
        uint32_t limit_y = info.height - 12;
        uint32_t limit_x1 = info.width - 12, limit_x2 = info.width - 6;

        if (x >= info.width || y > limit_y || !string) return -1;

        blk.x = 0;
        blk.w = info.width;
        blk.y = y;
        while (*s) {
                if (*s & 0x80) {
                        if (x > limit_x1) {
                                x = 0;
                                y += 12;
                                if (y > limit_y) break;
                        }
                        read_sys_hzk((94 * (*s - 0xa1) + (*(s + 1) - 0xa1)) * 24,
                                        font_buf, 24);
                        _lcd_disp_img(x, y, 12, 12, font_buf);
                        x += 12;
                        s += 2;
                }
                else {
                        if (*s == '\n') {
                                x = 0;
                                y += 12;
                                if (y > limit_y) {
                                        break;
                                }
                                s ++;
                                continue;
                        }
                        else if (*s == '\r') {
                                x = 0;
                                s ++;
                                continue;
                        }
                        if (x > limit_x2) {
                                x = 0;
                                y += 12;
                                if (y > limit_y) break;
                        }
                        read_sys_asc((*s) * 12, font_buf, 12);
                        _lcd_disp_img(x, y, 6, 12, font_buf);
                        x += 6;
                        s ++;
                }
        }
        if (y > limit_y) y -= 12;
        blk.h = y - blk.y + 12;
        ioctl(lcd_fd, IOCTL_LCD_UPDATE, &blk);
        return 0;
}

void timeouts_start( uint32_t start_time );
int timeouts_test( uint32_t timeout  );

#define PIN_INPUT_TIMEOUT		-3
#define PIN_INPUT_QUIT		-4
int get_ascii_str(uint32_t x, uint32_t y, char * buf, uint32_t minlen,
                uint32_t maxlen, uint32_t secs, char show)
{
	uint8_t font_[12], font_ept[12], font_buf[12];
	int key, count = 0;
	lcd_block_t blk;
	uint32_t bx = 0;

	if (buf == NULL) return -1;
	if (y > info.height - 12) return -1;
	if (x > info.width  - 6) return -1;
	if (maxlen < minlen) return -1;
	if (maxlen == 0) return 0;

	blk.x = x;
	blk.y = y;
	blk.w = ((info.width - x) / 6) * 6;
	blk.h = (maxlen / (blk.w / 6) + 1) * 12;
	if ((blk.h +y) > info.height) return -1;

	read_sys_asc('_' * 12, font_, 12);
	read_sys_asc(' ' * 12, font_ept, 12);
	if (show != 0)
	read_sys_asc(show * 12, font_buf, 12);
	timeouts_start( 0 );
	while (1) {
		_lcd_disp_img(x, y, 6, 12, font_);
		ioctl(lcd_fd, IOCTL_LCD_UPDATE, &blk);
		if( secs != 0 && timeouts_test( secs )){ 
			memset( buf, 0, count );		//clear sensitive data
			return PIN_INPUT_TIMEOUT;
		}

		key = kb_get_key( 1000 );
		if (key == KEY_ESC || key < 0){ 
			memset( buf, 0, count );		//clear sensitive data
			if( key == KEY_ESC )
				return PIN_INPUT_QUIT;
			return -1;
		}
		else if( key == 0 ) continue;
		else if (key == KEY_ENTER) {
			if (count == 0) break;
			if (count >= minlen) break;
		}
		else if (key == KEY_BS) {
			if (count == 0) continue;
			count --;
			_lcd_disp_img(x, y, 6, 12, font_ept);
			if (x < 6 || x <= blk.x) {
				y -= 12;
				x = bx + 6;
			}
			x -= 6;
			_lcd_disp_img(x, y, 6, 12, font_ept);
		}
		else if (key >= '0' && key <= '9') {
			if (count == maxlen) continue;
			buf[count ++] = key;
			if (show == 0)
				read_sys_asc(key * 12, font_buf, 12);
			_lcd_disp_img(x, y, 6, 12, font_buf);
#if 0
			if (count == maxlen) {
				ioctl(lcd_fd, IOCTL_LCD_UPDATE, &blk);
				break;
			}
#endif
			x += 6;
			if (x > (info.width  - 6)) {
				bx = x - 6;
				x = blk.x ;
				y += 12;
			}
		}
	}
	buf[count] = 0;
	return count;
}
